package com.edu.scnu.manager;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import javax.swing.ImageIcon;

import com.edu.scnu.element.ElementObj;
import com.edu.scnu.element.Enemy;

/**
 * @说明 加载器（工具：用户读取配置文件的工具）工具类，大多提供的是static方法
 * @author 14737
 */
public class GameLoad {
	private static ElementManager em = ElementManager.getManager();

	// 图片集合 使用map来进行存储 扩展：枚举类型配合移动(扩展)
	public static Map<String, ImageIcon> imgMap = new HashMap<>();
	public static Map<String, List<ImageIcon>> imgMaps;
	public static Map<String, ImageIcon> mapImgs = new HashMap<>();

	// 用户读取文件的类
	private static Properties pro = new Properties();

	/**
	 * @说明 传入地图id由加载方法依据文件规则自动产生地图文件名称，加载文件
	 * @param mapId 文件编号，文件id
	 */
	public static void MapLoad(int mapId) {
		loadObj();
		ElementObj obj = getObj("map");
		ElementObj map = obj.createElement("0,-600," + mapId);
		em.addElement(map, GameElement.MAPS);
	}

	/**
	 * @说明 加载图片代码
	 *     加载图片 代码和图片之间差 一个 路径问题
	 */
	public static void loadImg() { // 建议带参数，因为不同的关也可能需要不一样的图片资源
		String textUrl = "com/edu/scnu/text/GameData.pro"; // 文件的命名可以更加有规律
		ClassLoader classLoader = GameLoad.class.getClassLoader();
		InputStream texts = classLoader.getResourceAsStream(textUrl);
		// imgMap 用于存放参数
		pro.clear();
		try {
			pro.load(texts);
			Set<Object> set = pro.keySet();
			for (Object o : set) {
				String url = pro.getProperty(o.toString());
				imgMap.put(o.toString(), new ImageIcon(url));
			}
		} catch (IOException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
	}

	/**
	 * @说明 加载玩家
	 */
	public static void loadPlay() {
		loadObj();
		String playStr = "260,710,play";
		ElementObj obj = getObj("play");
		ElementObj play = obj.createElement(playStr);
		// ElementObj play = new Play().createElement(playStr);
		// 解耦，降低代码和代码之间的耦合度
		em.addElement(play, GameElement.PLAY);
	}

	/**
	 * @说明 加载敌人
	 */
	public static void loadEnemy(int GuanQiaId) {
		loadObj();
		int loadId = 0;// 用于加载对应关卡的敌人
		String enemyName = "com/edu/scnu/text/guanqia.pro";
		// 使用io流来获取文件对象
		ClassLoader classLoader = GameLoad.class.getClassLoader();
		InputStream enemys = classLoader.getResourceAsStream(enemyName);
		// System.out.println(enemys);//验证读取文件

		if (enemys == null) {
			System.out.println("配置文件读取异常，请重新安装");
			System.exit(0);
		}

		try {
			// 以后用的都是xml 和 json
			pro.clear();
			pro.load(enemys);
			// 可以直接动态的获取所有的key，有key就可以获取value
			Enumeration<?> names = pro.propertyNames();
			// 这样的迭代都有一个问题，一次迭代一个元素
			String key = String.valueOf(GuanQiaId);
			// System.out.println(key);
			// System.out.println(pro.getProperty(key));
			String[] arrs = pro.getProperty(key).split(";");
			for (int i = 0; i < arrs.length; i++) {
				// System.out.println(arrs[i]);
				ElementObj element = getObj("enemy").createElement(arrs[i]);
				// System.out.println(element);
				em.getElementsByKey(GameElement.ENEMY).add(element);
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public static void loadBoss(int GuanQiaId) {
		loadObj();
		String bossStr = "0,10,5,500";
		ElementObj obj = getObj("boss");
		// System.out.println(obj);
		ElementObj boss = obj.createElement(bossStr);
		// System.out.println(boss);
		// ElementObj play = new Play().createElement(playStr);
		// 解耦，降低代码和代码之间的耦合度
		if (5 == GuanQiaId)
			em.addElement(boss, GameElement.BOSS);
	}

	/**
	 * @说明 控制将敌人实例加入到资源管理器的方法
	 * @设计思路 要求随时间生成敌人，需要时间控制才可以做到，但只有gamerun中有时间控制，如果在gamerun中调用load
	 */
	public static void addEnemy(List<ElementObj> list, long gameTime) {
		for (ElementObj e : list) {
			if (gameTime == e.getBornTime()) {
				em.addElement(e, GameElement.ENEMY);
			}
		}
	}

	public static ElementObj getObj(String str) {
		try {
			Class<?> class1 = objMap.get(str);
			Object newInstance = class1.newInstance();
			if (newInstance instanceof ElementObj) {
				return (ElementObj) newInstance; // 这个对象就会new Play()等价。
				// 新建立一个叫GamePlay的类，若需要修改，用老方法很麻烦，该方法只需改配置文件就行
			}
		} catch (InstantiationException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * @说明 扩展 使用配置文件来实例化对象，通过固定的key（字符串来实例化）
	 */
	private static Map<String, Class<?>> objMap = new HashMap<>();

	public static void loadObj() {
		String textUrl = "com/edu/scnu/text/obj.pro"; // 文件的命名可以更加有规律
		ClassLoader classLoader = GameLoad.class.getClassLoader();
		InputStream texts = classLoader.getResourceAsStream(textUrl);
		pro.clear();
		try {
			pro.load(texts);
			Set<Object> set = pro.keySet();
			for (Object o : set) {
				String classUrl = pro.getProperty(o.toString());
				// 使用反射的方式直接将类进行获取
				Class<?> forName = Class.forName(classUrl);
				objMap.put(o.toString(), forName);
			}
		} catch (IOException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
	}

	public static void loadText(String str) {
		loadObj();
		List<ElementObj> play = em.getGameElements().get(GameElement.PLAY);
		ElementObj obj = getObj("text");
		ElementObj score = obj.createElement(str);
		// ElementObj play = new Play().createElement(playStr);
		// 解耦，降低代码和代码之间的耦合度
		em.addElement(score, GameElement.TEXT);
	}

}
